const http = require('http');
const https = require('https');
const { URL } = require('url');
const { SocksProxyAgent } = require('socks-proxy-agent');

class CloudHTTPProxy {
    constructor(options = {}) {
        this.port = options.port || 3000;
        this.host = options.host || '0.0.0.0';
        this.socksProxy = options.socksProxy || process.env.SOCKS_PROXY;
        this.auth = options.auth;
        this.allowedIPs = options.allowedIPs;
        this.maxConnections = options.maxConnections || 100;
        this.debug = options.debug || false;
        this.upstreamAgent = this.socksProxy ? new SocksProxyAgent(this.socksProxy) : null;
        this.server = http.createServer();
        this.connections = new Map(); // 改用 Map 存储连接信息
        this.stats = {
            totalConnections: 0,
            activeConnections: 0,
            totalRequests: 0,
            errors: 0
        };
        this.setupEventHandlers();
    }

    log(level, message, extra = {}) {
        const timestamp = new Date().toISOString();
        const logEntry = {
            timestamp,
            level,
            message,
            ...extra
        };
        
        if (level === 'error' || level === 'warn' || this.debug) {
            console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`, 
                Object.keys(extra).length > 0 ? extra : '');
        }
    }

    setupEventHandlers() {
        this.server.on('connect', this.handleConnect.bind(this));
        this.server.on('request', this.handleRequest.bind(this));
        this.server.on('error', this.handleError.bind(this));
        this.server.on('connection', this.handleConnection.bind(this));
        
        // 定期清理统计
        setInterval(() => {
            this.cleanupStats();
        }, 60000); // 每分钟清理一次
    }

    cleanupStats() {
        this.stats.activeConnections = this.connections.size;
        if (this.debug) {
            this.log('info', 'Stats', this.stats);
        }
    }

    getClientIP(req) {
        return req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
               req.headers['x-real-ip'] ||
               req.connection?.remoteAddress ||
               req.socket?.remoteAddress ||
               'unknown';
    }

    isIPAllowed(ip) {
        if (!this.allowedIPs || this.allowedIPs.length === 0) {
            return true;
        }
        const cleanIP = ip.replace(/^::ffff:/, '');
        return this.allowedIPs.includes(cleanIP);
    }

    validateAuth(req) {
        if (!this.auth) return true;

        const authHeader = req.headers['proxy-authorization'];
        if (!authHeader) return false;

        try {
            const [type, credentials] = authHeader.split(' ');
            if (type !== 'Basic') return false;

            const [username, password] = Buffer.from(credentials, 'base64').toString().split(':');
            return username === this.auth.username && password === this.auth.password;
        } catch (error) {
            this.log('warn', 'Auth validation error', { error: error.message });
            return false;
        }
    }

    handleConnection(socket) {
        this.stats.totalConnections++;
        
        if (this.connections.size >= this.maxConnections) {
            this.log('warn', 'Max connections reached, rejecting', { 
                current: this.connections.size,
                max: this.maxConnections 
            });
            socket.destroy();
            return;
        }

        const connectionId = `${socket.remoteAddress}:${socket.remotePort}-${Date.now()}`;
        const connectionInfo = {
            id: connectionId,
            remoteAddress: socket.remoteAddress,
            remotePort: socket.remotePort,
            startTime: Date.now()
        };

        this.connections.set(socket, connectionInfo);
        this.stats.activeConnections = this.connections.size;

        // 设置 socket 选项
        socket.setKeepAlive(true, 60000);
        socket.setTimeout(120000); // 2分钟超时

        socket.on('close', (hadError) => {
            this.connections.delete(socket);
            this.stats.activeConnections = this.connections.size;
            
            if (this.debug) {
                const duration = Date.now() - connectionInfo.startTime;
                this.log('debug', 'Connection closed', { 
                    connectionId,
                    hadError,
                    duration: `${duration}ms`
                });
            }
        });

        socket.on('error', (err) => {
            this.stats.errors++;
            const connInfo = this.connections.get(socket);
            
            // 只记录非常见的错误
            if (!this.isCommonError(err)) {
                this.log('warn', 'Socket error', { 
                    error: err.message,
                    code: err.code,
                    connectionId: connInfo?.id
                });
            }
            
            this.connections.delete(socket);
            this.stats.activeConnections = this.connections.size;
        });

        socket.on('timeout', () => {
            this.log('debug', 'Socket timeout', { connectionId });
            socket.destroy();
        });

        if (this.debug) {
            this.log('debug', 'New connection', connectionInfo);
        }
    }

    isCommonError(err) {
        const commonErrors = [
            'ECONNRESET',
            'EPIPE',
            'ECONNABORTED',
            'ETIMEDOUT'
        ];
        return commonErrors.includes(err.code);
    }

    handleConnect(req, clientSocket, head) {
        this.stats.totalRequests++;
        const clientIP = this.getClientIP(req);
        const startTime = Date.now();
        const requestId = `CONNECT-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
        
        this.log('info', 'CONNECT request', { 
            requestId,
            url: req.url,
            clientIP 
        });

        // IP 验证
        if (!this.isIPAllowed(clientIP)) {
            this.log('warn', 'IP not allowed', { requestId, clientIP });
            this.sendResponse(clientSocket, 403, 'Forbidden');
            return;
        }

        // 认证验证
        if (!this.validateAuth(req)) {
            this.log('warn', 'Auth failed', { requestId, clientIP });
            this.sendResponse(clientSocket, 407, 'Proxy Authentication Required', {
                'Proxy-Authenticate': 'Basic realm="Proxy"'
            });
            return;
        }

        try {
            const { hostname, port } = new URL(`http://${req.url}`);
            const serverPort = port || 443;

            this.log('debug', 'Connecting to target', { 
                requestId,
                hostname,
                port: serverPort 
            });

            this.createTargetConnection(hostname, serverPort, clientSocket, requestId, startTime);

        } catch (error) {
            this.log('error', 'CONNECT parsing error', { 
                requestId,
                error: error.message 
            });
            this.sendResponse(clientSocket, 400, 'Bad Request');
        }
    }

    createTargetConnection(hostname, port, clientSocket, requestId, startTime) {
        if (this.upstreamAgent) {
            // 通过 SOCKS 代理连接
            this.upstreamAgent.connect({ host: hostname, port }, (err, targetSocket) => {
                if (err) {
                    this.log('error', 'SOCKS connection failed', { 
                        requestId,
                        hostname,
                        port,
                        error: err.message 
                    });
                    this.sendResponse(clientSocket, 500, 'Connection Error');
                    return;
                }

                this.establishTunnel(clientSocket, targetSocket, requestId, hostname, port, startTime);
            });
        } else {
            // 直接连接
            const net = require('net');
            const targetSocket = new net.Socket();

            targetSocket.setTimeout(30000);
            
            targetSocket.connect(port, hostname, () => {
                this.establishTunnel(clientSocket, targetSocket, requestId, hostname, port, startTime);
            });

            targetSocket.on('error', (err) => {
                this.log('error', 'Target connection failed', { 
                    requestId,
                    hostname,
                    port,
                    error: err.message 
                });
                
                if (!clientSocket.destroyed) {
                    this.sendResponse(clientSocket, 500, 'Connection Error');
                }
            });

            targetSocket.on('timeout', () => {
                this.log('warn', 'Target connection timeout', { requestId, hostname, port });
                targetSocket.destroy();
                if (!clientSocket.destroyed) {
                    this.sendResponse(clientSocket, 504, 'Gateway Timeout');
                }
            });
        }
    }

    establishTunnel(clientSocket, targetSocket, requestId, hostname, port, startTime) {
        const duration = Date.now() - startTime;
        
        this.log('info', 'Tunnel established', { 
            requestId,
            hostname,
            port,
            duration: `${duration}ms`
        });

        // 发送连接成功响应
        if (!clientSocket.destroyed) {
            clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
        }

        // 建立双向数据流
        targetSocket.pipe(clientSocket).on('error', (err) => {
            if (!this.isCommonError(err)) {
                this.log('warn', 'Target->Client pipe error', { 
                    requestId,
                    error: err.message 
                });
            }
        });

        clientSocket.pipe(targetSocket).on('error', (err) => {
            if (!this.isCommonError(err)) {
                this.log('warn', 'Client->Target pipe error', { 
                    requestId,
                    error: err.message 
                });
            }
        });

        // 清理函数
        const cleanup = () => {
            if (!targetSocket.destroyed) targetSocket.destroy();
            if (!clientSocket.destroyed) clientSocket.destroy();
        };

        targetSocket.on('close', cleanup);
        clientSocket.on('close', cleanup);
        targetSocket.on('error', cleanup);
        clientSocket.on('error', cleanup);
    }

    sendResponse(socket, statusCode, statusText, headers = {}) {
        if (socket.destroyed) return;
        
        try {
            let response = `HTTP/1.1 ${statusCode} ${statusText}\r\n`;
            
            Object.entries(headers).forEach(([key, value]) => {
                response += `${key}: ${value}\r\n`;
            });
            
            response += '\r\n';
            socket.write(response);
            socket.end();
        } catch (error) {
            socket.destroy();
        }
    }

    handleRequest(req, res) {
        this.stats.totalRequests++;
        const clientIP = this.getClientIP(req);
        const startTime = Date.now();
        const requestId = `HTTP-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
        
        this.log('info', 'HTTP request', { 
            requestId,
            method: req.method,
            url: req.url,
            clientIP 
        });

        // IP 验证
        if (!this.isIPAllowed(clientIP)) {
            this.log('warn', 'IP not allowed', { requestId, clientIP });
            res.writeHead(403, { 'Content-Type': 'text/plain' });
            res.end('Forbidden: IP not allowed');
            return;
        }

        // 认证验证
        if (!this.validateAuth(req)) {
            this.log('warn', 'Auth failed', { requestId, clientIP });
            res.writeHead(407, {
                'Proxy-Authenticate': 'Basic realm="Proxy"',
                'Content-Type': 'text/plain'
            });
            res.end('Proxy Authentication Required');
            return;
        }

        // 状态页面
        let url;
        try {
            url = new URL(req.url);
        } catch (error) {
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                message: '云端 HTTP 代理服务器',
                status: 'running',
                stats: this.stats,
                clientIP: clientIP,
                timestamp: new Date().toISOString()
            }, null, 2));
            return;
        }

        this.proxyHTTPRequest(req, res, url, requestId, startTime);
    }

    proxyHTTPRequest(req, res, url, requestId, startTime) {
        const options = {
            hostname: url.hostname,
            port: url.port || (url.protocol === 'https:' ? 443 : 80),
            path: url.pathname + url.search,
            method: req.method,
            headers: { ...req.headers },
            timeout: 30000
        };

        // 清理头部
        delete options.headers['proxy-connection'];
        delete options.headers['proxy-authorization'];
        options.headers['host'] = url.hostname;

        if (this.upstreamAgent) {
            options.agent = this.upstreamAgent;
        }

        const httpModule = url.protocol === 'https:' ? https : http;

        const proxyReq = httpModule.request(options, (proxyRes) => {
            const duration = Date.now() - startTime;
            this.log('info', 'HTTP response', { 
                requestId,
                hostname: url.hostname,
                statusCode: proxyRes.statusCode,
                duration: `${duration}ms`
            });

            res.writeHead(proxyRes.statusCode, proxyRes.headers);
            proxyRes.pipe(res);
        });

        proxyReq.on('error', (err) => {
            const duration = Date.now() - startTime;
            this.log('error', 'HTTP request failed', { 
                requestId,
                hostname: url.hostname,
                error: err.message,
                duration: `${duration}ms`
            });
            
            if (!res.headersSent) {
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.end(`Proxy Error: ${err.message}`);
            }
        });

        proxyReq.on('timeout', () => {
            this.log('warn', 'HTTP request timeout', { requestId, hostname: url.hostname });
            proxyReq.abort();
            if (!res.headersSent) {
                res.writeHead(504, { 'Content-Type': 'text/plain' });
                res.end('Gateway Timeout');
            }
        });

        req.pipe(proxyReq);

        req.on('aborted', () => {
            proxyReq.abort();
        });
    }

    handleError(err) {
        this.stats.errors++;
        this.log('error', 'Server error', { error: err.message, code: err.code });
    }

    start() {
        this.server.listen(this.port, this.host, () => {
            console.log(`🚀 云端 HTTP 代理服务器启动成功`);
            console.log(`📡 监听地址: ${this.host}:${this.port}`);
            console.log(`🌐 公网配置:`);
            console.log(`   协议: HTTP`);
            console.log(`   服务器: YOUR_SERVER_IP`);
            console.log(`   端口: ${this.port}`);
            console.log(`📊 最大连接数: ${this.maxConnections}`);
            console.log(`🐛 调试模式: ${this.debug ? '开启' : '关闭'}`);
            
            if (this.socksProxy) {
                console.log(`🔒 上游代理: ${this.socksProxy}`);
            }
            if (this.auth) {
                console.log(`🔐 需要认证: 是`);
            }
            if (this.allowedIPs) {
                console.log(`✅ IP 白名单: ${this.allowedIPs.join(', ')}`);
            }
        });

        this.server.on('error', (err) => {
            if (err.code === 'EADDRINUSE') {
                console.error(`❌ 端口 ${this.port} 已被占用`);
            } else {
                console.error('服务器启动错误:', err);
            }
        });
    }

    stop() {
        return new Promise((resolve) => {
            this.connections.forEach((info, socket) => {
                socket.destroy();
            });
            this.server.close(resolve);
        });
    }

    // 获取统计信息
    getStats() {
        return {
            ...this.stats,
            activeConnections: this.connections.size,
            uptime: process.uptime()
        };
    }
}

// 启动代理服务器
const proxy = new CloudHTTPProxy({
    port: 3000,
    host: '0.0.0.0',
    debug: process.env.DEBUG === 'true', // 设置 DEBUG=true 开启详细日志
    maxConnections: 200,
    socksProxy: 'socks5://127.0.0.1:1080'
});

proxy.start();

// 定期输出统计信息
setInterval(() => {
    const stats = proxy.getStats();
    console.log(`📊 [${new Date().toISOString()}] 统计: 活跃连接=${stats.activeConnections}, 总请求=${stats.totalRequ求}, 错误=${stats.errors}`);
}, 300000); // 每5分钟

// 优雅关闭
process.on('SIGINT', async () => {
    console.log('\n🛑 正在关闭代理服务器...');
    await proxy.stop();
    console.log('✅ 代理服务器已关闭');
    process.exit(0);
});

process.on('uncaughtException', (err) => {
    console.error('未捕获异常:', err);
});

process.on('unhandledRejection', (reason, promise) => {
    console.error('未处理的 Promise 拒绝:', reason);
});

module.exports = CloudHTTPProxy;
